package com.nami.gate.network.handler;


import cn.hutool.json.JSONUtil;

import com.nami.gate.constants.ChannelConstants;
import com.nami.gate.external.basic.constants.UpTopicConst;
import com.nami.gate.external.basic.request.upmsg.HeartTimeoutRequest;
import com.nami.gate.middleware.mq.MqSender;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;


@Slf4j
public class HeartBeatHandler extends ChannelInboundHandlerAdapter {

    private int heartBeatTime;

    private MqSender mqSender;

    public HeartBeatHandler(int heartBeatTime, MqSender mqSender) {
        this.heartBeatTime = heartBeatTime * 1000;
        this.mqSender = mqSender;
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // 判断 evt 是否是 IdleStateEvent (用于触发用户事件，包含 读空闲/写空闲/读写空闲
        if (evt instanceof IdleStateEvent) {
            // 强制类型转换
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                log.info("[hearbeat] [{}]进入读空闲...", ctx.channel().remoteAddress());
            } else if (event.state() == IdleState.WRITER_IDLE) {
                log.info("[hearbeat] [{}]进入写空闲...", ctx.channel().remoteAddress());
            } else if (event.state() == IdleState.ALL_IDLE) {
                Long lastReadTime = (Long) ctx.channel().attr(AttributeKey.valueOf(
                    ChannelConstants.READ_TIME)).get();
//                long nowReadTime = SystemClock.now();
                if (lastReadTime != null && (System.currentTimeMillis() - lastReadTime) > heartBeatTime) {
                    logout(ctx);
                    return;
                }

                // TODO 握手成功，但未认证成功的client 移除
                if (lastReadTime == null) {
                    try {
                        Integer times = (Integer) ctx.channel().attr(AttributeKey.valueOf(
                            ChannelConstants.ALL_IDLE_TIMES)).get();
                        if (times != null && times >= 10) {
                            log.warn("[hearbeat] 将握手成功，未认证client移除.");
                            ctx.channel().close();
                        }
                        times = times == null ? 1 : times + 1;
                        ctx.channel().attr(AttributeKey.valueOf(
                            ChannelConstants.ALL_IDLE_TIMES)).set(times);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }
        }
    }

    private void logout(ChannelHandlerContext ctx) {
        try {
            // 用户退后台
            HeartTimeoutRequest request = new HeartTimeoutRequest();
            Channel channel = ctx.channel();
            request.setUserId((String) channel.attr(AttributeKey.valueOf(ChannelConstants.USER_ID)).get());
            request.setAppKey((String) channel.attr(AttributeKey.valueOf(ChannelConstants.APP_KEY)).get());
            request.setInstanceId((String) channel.attr(AttributeKey.valueOf(ChannelConstants.INSTANCE_ID)).get());
            request.setCurrTime(System.currentTimeMillis());
            log.error("[heartbeat] 用户心跳超时。user={}", JSONUtil.toJsonStr(request));
            mqSender.send(UpTopicConst.CONNECT_TIMEOUT_TOPIC, JSONUtil.toJsonStr(request));
        } catch (Exception var3) {
            var3.printStackTrace();
            log.error("[heartbeat] 出错误. msg={}", var3.getMessage());
        }
    }

}
